package com.lagou.wuxi.factory;

import com.lagou.wuxi.anno.*;
import com.lagou.wuxi.utils.ClasspathPackageScanner;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * 工厂类，生产对象（使用反射技术）
 */
public class BeanFactory {

    // 扫描的默认包路径，偷个懒就不放配置文件了
    private static final String BASE_PACKAGE= "com.lagou.wuxi";

    // 默认按照id装配
    private static Map<String, Object> map = new HashMap<>();  // 存储对象

    // 事务代理类工厂
    private static ProxyFactory proxyFactory = ProxyFactory.getInstance();

    static {
        try {
            // 扫描注解，装配IOC容器
            List<String> fullyQualifiedClassNameList = new ClasspathPackageScanner(BASE_PACKAGE).getFullyQualifiedClassNameList();
            for (String clazz : fullyQualifiedClassNameList) {
                Class<?> aClass = null;
                aClass = Class.forName(clazz);

                Component component = aClass.getAnnotation(Component.class);
                Dao dao = aClass.getAnnotation(Dao.class);
                Service service = aClass.getAnnotation(Service.class);
                Controller controller = aClass.getAnnotation(Controller.class);

                boolean need = null != controller || null != service || null != dao || null != component;

                if(need){
                    String id = null != controller ? controller.id() : (null != service ? service.id() : ( null != dao ? dao.id() : component.id()));

                    Object o = aClass.newInstance();
                    System.out.println("init bean: " + aClass.getName());
                    map.put(id, o);
                }
            }

            // 解决依赖关系
            if(map.size() > 0){
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    String id = entry.getKey();
                    Object value = entry.getValue();

                    Field[] declaredFields = value.getClass().getDeclaredFields();
                    if(null != declaredFields && declaredFields.length > 0){
                        for (Field declaredField : declaredFields) {
                            Autowired annotation = declaredField.getAnnotation(Autowired.class);
                            if(null != annotation){
                                Object fieldValue = map.get(annotation.id());
                                if(null == fieldValue){
                                    System.out.println("missing bean " + declaredField.getType());
                                    throw new IllegalArgumentException();
                                }
                                declaredField.setAccessible(true);
                                declaredField.set(value, fieldValue);
                            }
                        }
                    }

                    Transactional annotation = value.getClass().getAnnotation(Transactional.class);
                    if(null != annotation){
                        // 如果有Transactional注解，自动替换为代理对象
                        if(value.getClass().getInterfaces().length > 0){
                            // 实现了接口，jdk动态代理
                            value = proxyFactory.getJdkProxy(value);
                        } else {
                            // 没有实现接口，cglib动态代理
                            value = proxyFactory.getCglibProxy(value);
                        }
                        map.put(id, value);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 任务二：对外提供获取实例对象的接口（根据id获取）
    public static  Object getBean(String id) {
        return map.get(id);
    }

}
